package net.loyintean.pearlshell.validation.util;

import net.loyintean.pearlshell.base.model.IResult;
import net.loyintean.pearlshell.base.model.impl.ResultFactory;
import net.loyintean.pearlshell.validation.IValidField;
import net.loyintean.pearlshell.validation.IValidRule;
import net.loyintean.pearlshell.validation.IValidRuleConfig;
import net.loyintean.pearlshell.validation.exception.ForceInteruptException;
import net.loyintean.pearlshell.validation.rule.IValidFactory;

/**
 * 对输入的内容进行校验
 * 
 * @author linjun-ghq
 */
public class ValidUtil {

	private static final String SUCCESS = "校验通过";

	private static final IValidFactory FACTORY = IValidFactory.SINGLETON_FACTORY;

	private ValidUtil() {
		throw new RuntimeException("不允许使用ValidUtil的实例！");
	}

	/**
	 * 按照校验规则配置，依次校验toVaid
	 * 
	 * @param toValid
	 * @param ruleConfigList
	 * @return
	 * @throws ForceInteruptException
	 */
	private static final String valid(Object toValid,
			IValidRuleConfig... ruleConfigList) throws ForceInteruptException {
		// assert ruleConfigList != null;
		// assert ruleConfigList.length > 0;

		if (ruleConfigList == null || ruleConfigList.length == 0) {
			throw new IllegalArgumentException("校验规则配置信息数组不能为空！");
		}

		for (int configIndex = 0; configIndex < ruleConfigList.length; configIndex++) {

			IValidRuleConfig config = ruleConfigList[configIndex];
			// assert config != null;

			if (config == null) {
				throw new IllegalArgumentException("校验规则配置信息不能为空！");
			}

			IValidRule rule = FACTORY.buildRule(config);

			// assert rule != null;

			if (rule == null) {
				throw new IllegalArgumentException("根据校验配置信息获取的校验规则不能为空！");
			}

			if (!rule.valid(toValid, config)) {

				return rule.errorMsg(config);

			}

		}

		return SUCCESS;
	}

	/**
	 * 根据入参提供的校验配置，对入参数据进行校验。
	 * 
	 * @param fields
	 *            入参字段，包括待校验数据、待校验字段名称和校验规则配置。
	 * @return 校验结果。不会校验出错字段的后续字段。
	 */
	public static final IResult<String> valid(IValidField... fields) {
		// DONE 这里应该做入参校验，而不是assert
		// 这个类是入口，而不是内部服务。
		// CLOSE rule实现类中对config的参数校验也不能用assert
		// assert fields != null;

		if (fields == null) {
			throw new IllegalArgumentException("待校验字段数组不能为空！");
		}

		IResult<String> result = ResultFactory.INIT();

		result.success(SUCCESS);

		String fieldResult = null;

		String fieldName = null;

		try {
			for (IValidField field : fields) {

				if (field == null) {
					throw new IllegalArgumentException("待校验字段不能为空！");
				} else {
					fieldName = field.name();
				}

				fieldResult = valid(field.value(), field.configs());

				if (!SUCCESS.equals(fieldResult)) {
					// 将result中的data也修改为错误信息。
					result.fail(fieldName + fieldResult, fieldName
							+ fieldResult);

					break;
				}
			}
		} catch (ForceInteruptException fie) {

			result.fail(fieldName + fie.getMessage());

		} catch (IllegalArgumentException e) {
			if (fieldName == null) {
				throw e;
			} else {
				throw new IllegalArgumentException("对字段 " + fieldName
						+ " 进行校验时发生异常！", e);
			}
		}

		return result;

	}
}
